#include "No7pch.h"
#include "Matrixes.h"

#include <cmath>

template class nmspc::MatrixTemplate<2, 2, double>;

template nmspc::Matrix2X2D nmspc::Matrix2X2D::operator*(const nmspc::Matrix2X2D&);

template nmspc::Matrix2X2D& nmspc::Matrix2X2D::operator*=(const nmspc::Matrix2X2D&);

template nmspc::Matrix2X2D nmspc::Matrix2X2D::operator+(const nmspc::Matrix2X2D&);

template nmspc::Matrix2X2D& nmspc::Matrix2X2D::operator+=(const nmspc::Matrix2X2D&);

template class nmspc::MatrixTemplate<3, 3, double>;

template nmspc::Matrix3X3D nmspc::Matrix3X3D::operator*(const nmspc::Matrix3X3D&);

template nmspc::Matrix3X3D& nmspc::Matrix3X3D::operator*=(const nmspc::Matrix3X3D&);

template nmspc::Matrix3X3D nmspc::Matrix3X3D::operator+(const nmspc::Matrix3X3D&);

template nmspc::Matrix3X3D& nmspc::Matrix3X3D::operator+=(const nmspc::Matrix3X3D&);

template class nmspc::MatrixTemplate<4, 4, double>;

template nmspc::Matrix4X4D nmspc::Matrix4X4D::operator*(const nmspc::Matrix4X4D&);

template nmspc::Matrix4X4D& nmspc::Matrix4X4D::operator*=(const nmspc::Matrix4X4D&);

template nmspc::Matrix4X4D nmspc::Matrix4X4D::operator+(const nmspc::Matrix4X4D&);

template nmspc::Matrix4X4D& nmspc::Matrix4X4D::operator+=(const nmspc::Matrix4X4D&);

std::vector<nmspc::Matrix2X2D*> nmspc::Matrix2X2DFactory::matrixes = std::vector<nmspc::Matrix2X2D*>(3);

bool nmspc::Matrix2X2DFactory::if_generated_final_matrix = false;

std::mutex nmspc::Matrix2X2DFactory::matrixes_mtx;

std::vector<std::stack<nmspc::Matrix2X2D*>> nmspc::Matrix2X2DFactory::used_matrixes = std::vector<std::stack<nmspc::Matrix2X2D*>>(3);

std::stack<bool> nmspc::Matrix2X2DFactory::used_if_generated_final_matrix;

std::mutex nmspc::Matrix2X2DFactory::used_matrixes_mtx;

void nmspc::Matrix2X2DFactory::refreshFinalMatrix()
{
	if (nmspc::Matrix2X2DFactory::matrixes[0] == nullptr)
	{
		nmspc::Matrix2X2DFactory::matrixes[0] = nmspc::Matrix2X2D::generateIdentityMatrixPtr();
	}
	else
	{
		(*nmspc::Matrix2X2DFactory::matrixes[0])[0][0] = (*nmspc::Matrix2X2DFactory::matrixes[0])[1][1] = 1.0l;
		(*nmspc::Matrix2X2DFactory::matrixes[0])[0][1] = (*nmspc::Matrix2X2DFactory::matrixes[0])[1][0] = 0.0l;
	}
	nmspc::Matrix2X2DFactory::if_generated_final_matrix = false;
}

nmspc::Matrix2X2D nmspc::Matrix2X2DFactory::generateNormalMatrix(const std::vector<std::vector<double>>& data)
{
	return nmspc::Matrix2X2D(data);
}

const nmspc::Matrix2X2D* nmspc::Matrix2X2DFactory::generateScaleMatrix(const double& ratio1, const double& ratio2)
{
	std::lock_guard<std::mutex> lock(nmspc::Matrix2X2DFactory::matrixes_mtx);
	if (nmspc::Matrix2X2DFactory::matrixes[1] == nullptr)
	{
		nmspc::Matrix2X2DFactory::matrixes[1] = nmspc::Matrix2X2D::generateIdentityMatrixPtr();
	}
	(*nmspc::Matrix2X2DFactory::matrixes[1])[0][0] = ratio1;
	(*nmspc::Matrix2X2DFactory::matrixes[1])[1][1] = ratio2;
	nmspc::Matrix2X2DFactory::if_generated_final_matrix = false;
	return nmspc::Matrix2X2DFactory::matrixes[1];
}

const nmspc::Matrix2X2D* nmspc::Matrix2X2DFactory::generateRotateMatrix(const double& alpha)
{
	std::lock_guard<std::mutex> lock(nmspc::Matrix2X2DFactory::matrixes_mtx);
	if (nmspc::Matrix2X2DFactory::matrixes[2] == nullptr)
	{
		nmspc::Matrix2X2DFactory::matrixes[2] = nmspc::Matrix2X2D::generateIdentityMatrixPtr();
	}
	(*nmspc::Matrix2X2DFactory::matrixes[2])[0][0] = (*nmspc::Matrix2X2DFactory::matrixes[2])[1][1] = std::cos(alpha);
	(*nmspc::Matrix2X2DFactory::matrixes[2])[0][1] = std::sin(alpha);
	(*nmspc::Matrix2X2DFactory::matrixes[2])[1][0] = -(*nmspc::Matrix2X2DFactory::matrixes[2])[0][1];
	nmspc::Matrix2X2DFactory::if_generated_final_matrix = false;
	return nmspc::Matrix2X2DFactory::matrixes[2];
}

const nmspc::Matrix2X2D* nmspc::Matrix2X2DFactory::generateFinalMatrix()
{
	std::lock_guard<std::mutex> lock(nmspc::Matrix2X2DFactory::matrixes_mtx);
	if (!nmspc::Matrix2X2DFactory::if_generated_final_matrix)
	{
		nmspc::Matrix2X2DFactory::refreshFinalMatrix();
		for (std::int64_t i = 1; i < nmspc::Matrix2X2DFactory::matrixes.size(); i++)
		{
			if (nmspc::Matrix2X2DFactory::matrixes[i] != nullptr)
			{
				(*nmspc::Matrix2X2DFactory::matrixes[0]) *= (*nmspc::Matrix2X2DFactory::matrixes[i]);
			}
		}
		nmspc::Matrix2X2DFactory::if_generated_final_matrix = true;
	}
	return nmspc::Matrix2X2DFactory::matrixes[0];
}

void nmspc::Matrix2X2DFactory::refreshFunctionMatrixes()
{
	std::lock_guard<std::mutex> lock(nmspc::Matrix2X2DFactory::matrixes_mtx);
	for (std::int64_t i = 1; i < nmspc::Matrix2X2DFactory::matrixes.size(); i++)
	{
		if (nmspc::Matrix2X2DFactory::matrixes[i] == nullptr)
		{
			nmspc::Matrix2X2DFactory::matrixes[i] = nmspc::Matrix2X2D::generateIdentityMatrixPtr();
		}
		else
		{
			(*nmspc::Matrix2X2DFactory::matrixes[i])[0][0] = (*nmspc::Matrix2X2DFactory::matrixes[i])[1][1] = 1.0l;
			(*nmspc::Matrix2X2DFactory::matrixes[i])[0][1] = (*nmspc::Matrix2X2DFactory::matrixes[i])[1][0] = 0.0l;
		}
	}
	nmspc::Matrix2X2DFactory::if_generated_final_matrix = false;
}

void nmspc::Matrix2X2DFactory::refreshMatrixAt(const std::int64_t& index)
{
	if (index < 0 || index >= 3) return;
	std::lock_guard<std::mutex> lock(nmspc::Matrix2X2DFactory::matrixes_mtx);
	if (nmspc::Matrix2X2DFactory::matrixes[index] == nullptr)
	{
		nmspc::Matrix2X2DFactory::matrixes[index] = nmspc::Matrix2X2D::generateIdentityMatrixPtr();
	}
	else
	{
		(*nmspc::Matrix2X2DFactory::matrixes[index])[0][0] = (*nmspc::Matrix2X2DFactory::matrixes[index])[1][1] = 1.0l;
		(*nmspc::Matrix2X2DFactory::matrixes[index])[0][1] = (*nmspc::Matrix2X2DFactory::matrixes[index])[1][0] = 0.0l;
	}
	nmspc::Matrix2X2DFactory::if_generated_final_matrix = false;
}

void nmspc::Matrix2X2DFactory::refreshAll()
{
	std::lock_guard<std::mutex> lock(nmspc::Matrix2X2DFactory::matrixes_mtx);
	for (std::int64_t i = 0; i < nmspc::Matrix2X2DFactory::matrixes.size(); i++)
	{
		if (nmspc::Matrix2X2DFactory::matrixes[i] == nullptr)
		{
			nmspc::Matrix2X2DFactory::matrixes[i] = nmspc::Matrix2X2D::generateIdentityMatrixPtr();
		}
		else
		{
			(*nmspc::Matrix2X2DFactory::matrixes[i])[0][0] = (*nmspc::Matrix2X2DFactory::matrixes[i])[1][1] = 1.0l;
			(*nmspc::Matrix2X2DFactory::matrixes[i])[0][1] = (*nmspc::Matrix2X2DFactory::matrixes[i])[1][0] = 0.0l;
		}
	}
	nmspc::Matrix2X2DFactory::if_generated_final_matrix = false;
}

void nmspc::Matrix2X2DFactory::push()
{
	std::lock_guard<std::mutex> lock1(nmspc::Matrix2X2DFactory::matrixes_mtx);
	bool if_could_push = false;
	for (nmspc::Matrix2X2D*& matrix : nmspc::Matrix2X2DFactory::matrixes)
	{
		if (matrix != nullptr)
		{
			if_could_push = true;
			break;
		}
	}
	if (if_could_push)
	{
		std::lock_guard<std::mutex> lock2(nmspc::Matrix2X2DFactory::used_matrixes_mtx);
		for (std::int64_t i = 0; i < nmspc::Matrix2X2DFactory::matrixes.size(); i++)
		{
			nmspc::Matrix2X2DFactory::used_matrixes[i].push(nmspc::Matrix2X2DFactory::matrixes[i]);
			nmspc::Matrix2X2DFactory::matrixes[i] = nullptr;
		}
		nmspc::Matrix2X2DFactory::used_if_generated_final_matrix.push(nmspc::Matrix2X2DFactory::if_generated_final_matrix);
		nmspc::Matrix2X2DFactory::if_generated_final_matrix = false;
	}
}

void nmspc::Matrix2X2DFactory::pop()
{
	std::lock_guard<std::mutex> lock1(nmspc::Matrix2X2DFactory::matrixes_mtx);
	for (nmspc::Matrix2X2D*& matrix : nmspc::Matrix2X2DFactory::matrixes)
	{
		if (matrix != nullptr)
		{
			delete matrix;
		}
		matrix = nullptr;
	}
	nmspc::Matrix2X2DFactory::if_generated_final_matrix = false;
	std::lock_guard<std::mutex> lock2(nmspc::Matrix2X2DFactory::used_matrixes_mtx);
	if (nmspc::Matrix2X2DFactory::used_if_generated_final_matrix.empty()) return;
	for (std::int64_t i = 0; i < nmspc::Matrix2X2DFactory::matrixes.size(); i++)
	{
		nmspc::Matrix2X2DFactory::matrixes[i] = nmspc::Matrix2X2DFactory::used_matrixes[i].top();
		nmspc::Matrix2X2DFactory::used_matrixes[i].pop();
	}
	nmspc::Matrix2X2DFactory::if_generated_final_matrix = nmspc::Matrix2X2DFactory::used_if_generated_final_matrix.top();
	nmspc::Matrix2X2DFactory::used_if_generated_final_matrix.pop();
}

void nmspc::Matrix2X2DFactory::destory()
{
	std::lock_guard<std::mutex> lock1(nmspc::Matrix2X2DFactory::matrixes_mtx);
	for (nmspc::Matrix2X2D*& cur_matrix : nmspc::Matrix2X2DFactory::matrixes)
	{
		if (cur_matrix != nullptr)
		{
			delete cur_matrix;
		}
		cur_matrix = nullptr;
	}
	std::lock_guard<std::mutex> lock2(nmspc::Matrix2X2DFactory::used_matrixes_mtx);
	for (std::stack<nmspc::Matrix2X2D*>& cur_matriexes : nmspc::Matrix2X2DFactory::used_matrixes)
	{
		while (!cur_matriexes.empty())
		{
			delete cur_matriexes.top();
			cur_matriexes.pop();
		}
	}
	while (!nmspc::Matrix2X2DFactory::used_if_generated_final_matrix.empty())
	{
		nmspc::Matrix2X2DFactory::used_if_generated_final_matrix.pop();
	}
}

const nmspc::Matrix2X2D* nmspc::Matrix2X2DFactory::getScaleMatrix()
{
	std::lock_guard<std::mutex> lock(nmspc::Matrix2X2DFactory::matrixes_mtx);
	if (nmspc::Matrix2X2DFactory::matrixes[1] == nullptr)
	{
		nmspc::Matrix2X2DFactory::matrixes[1] = nmspc::Matrix2X2D::generateIdentityMatrixPtr();
	}
	return nmspc::Matrix2X2DFactory::matrixes[1];
}

const nmspc::Matrix2X2D* nmspc::Matrix2X2DFactory::getRotateMatrix()
{
	std::lock_guard<std::mutex> lock(nmspc::Matrix2X2DFactory::matrixes_mtx);
	if (nmspc::Matrix2X2DFactory::matrixes[2] == nullptr)
	{
		nmspc::Matrix2X2DFactory::matrixes[2] = nmspc::Matrix2X2D::generateIdentityMatrixPtr();
	}
	return nmspc::Matrix2X2DFactory::matrixes[2];
}

const nmspc::Matrix2X2D* nmspc::Matrix2X2DFactory::getFinalMatrix()
{
	return nmspc::Matrix2X2DFactory::generateFinalMatrix();
}

std::vector<nmspc::Matrix3X3D*> nmspc::MatrixFactoryIn2D::matrixes = std::vector<nmspc::Matrix3X3D*>(8);

bool nmspc::MatrixFactoryIn2D::if_generated_final_matrix = false;

bool nmspc::MatrixFactoryIn2D::if_generated_model_transformation_matrix = false;

std::mutex nmspc::MatrixFactoryIn2D::matrixes_mtx;

std::vector<std::stack<nmspc::Matrix3X3D*>> nmspc::MatrixFactoryIn2D::used_matrixes = std::vector<std::stack<nmspc::Matrix3X3D*>>(8);

std::stack<std::pair<bool, bool>> nmspc::MatrixFactoryIn2D::used_if_generated_final_or_model_transformation_matrixes;

std::mutex nmspc::MatrixFactoryIn2D::used_matrixes_mtx;

void nmspc::MatrixFactoryIn2D::refreshFinalMatrix()
{
	if (nmspc::MatrixFactoryIn2D::matrixes[0] == nullptr)
	{
		nmspc::MatrixFactoryIn2D::matrixes[0] = nmspc::Matrix3X3D::generateIdentityMatrixPtr();
	}
	else
	{
		nmspc::MatrixFactoryIn2D::matrixes[0]->unitization();
	}
	nmspc::MatrixFactoryIn2D::if_generated_final_matrix = false;
}

void nmspc::MatrixFactoryIn2D::refreshModelTransformationMatrix()
{
	if (nmspc::MatrixFactoryIn2D::matrixes[1] == nullptr)
	{
		nmspc::MatrixFactoryIn2D::matrixes[1] = nmspc::Matrix3X3D::generateIdentityMatrixPtr();
	}
	else
	{
		nmspc::MatrixFactoryIn2D::matrixes[1]->unitization();
	}
	nmspc::MatrixFactoryIn2D::if_generated_final_matrix = false;
	nmspc::MatrixFactoryIn2D::if_generated_model_transformation_matrix = false;
}

nmspc::Matrix3X3D nmspc::MatrixFactoryIn2D::generateNormalMatrix(const std::vector<std::vector<double>>& data)
{
	return nmspc::Matrix3X3D(data);
}

const nmspc::Matrix3X3D* nmspc::MatrixFactoryIn2D::generateScaleMatrix(const double& ratio1, const double& ratio2)
{
	std::lock_guard<std::mutex> lock(nmspc::MatrixFactoryIn2D::matrixes_mtx);
	if (nmspc::MatrixFactoryIn2D::matrixes[2] == nullptr)
	{
		nmspc::MatrixFactoryIn2D::matrixes[2] = nmspc::Matrix3X3D::generateIdentityMatrixPtr();
	}
	(*nmspc::MatrixFactoryIn2D::matrixes[2])[0][0] = ratio1;
	(*nmspc::MatrixFactoryIn2D::matrixes[2])[1][1] = ratio2;
	nmspc::MatrixFactoryIn2D::if_generated_final_matrix = false;
	nmspc::MatrixFactoryIn2D::if_generated_model_transformation_matrix = false;
	return nmspc::MatrixFactoryIn2D::matrixes[2];
}

const nmspc::Matrix3X3D* nmspc::MatrixFactoryIn2D::generateRotateMatrix(const double& alpha)
{
	std::lock_guard<std::mutex> lock(nmspc::MatrixFactoryIn2D::matrixes_mtx);
	if (nmspc::MatrixFactoryIn2D::matrixes[3] == nullptr)
	{
		nmspc::MatrixFactoryIn2D::matrixes[3] = nmspc::Matrix3X3D::generateIdentityMatrixPtr();
	}
	(*nmspc::MatrixFactoryIn2D::matrixes[3])[0][0] = (*nmspc::MatrixFactoryIn2D::matrixes[3])[1][1] = std::cos(alpha);
	(*nmspc::MatrixFactoryIn2D::matrixes[3])[0][1] = std::sin(alpha);
	(*nmspc::MatrixFactoryIn2D::matrixes[3])[1][0] = -(*nmspc::MatrixFactoryIn2D::matrixes[3])[0][1];
	nmspc::MatrixFactoryIn2D::if_generated_final_matrix = false;
	nmspc::MatrixFactoryIn2D::if_generated_model_transformation_matrix = false;
	return nmspc::MatrixFactoryIn2D::matrixes[3];
}

const nmspc::Matrix3X3D* nmspc::MatrixFactoryIn2D::generateTranslateMatrix(const double& delta_x, const double& delta_y)
{
	std::lock_guard<std::mutex> lock(nmspc::MatrixFactoryIn2D::matrixes_mtx);
	if (nmspc::MatrixFactoryIn2D::matrixes[4] == nullptr)
	{
		nmspc::MatrixFactoryIn2D::matrixes[4] = nmspc::Matrix3X3D::generateIdentityMatrixPtr();
	}
	(*nmspc::MatrixFactoryIn2D::matrixes[4])[2][0] = delta_x;
	(*nmspc::MatrixFactoryIn2D::matrixes[4])[2][1] = delta_y;
	nmspc::MatrixFactoryIn2D::if_generated_final_matrix = false;
	nmspc::MatrixFactoryIn2D::if_generated_model_transformation_matrix = false;
	return nmspc::MatrixFactoryIn2D::matrixes[4];
}

const nmspc::Matrix3X3D* nmspc::MatrixFactoryIn2D::generateModelTransformationMatrix()
{
	std::lock_guard<std::mutex> lock(nmspc::MatrixFactoryIn2D::matrixes_mtx);
	if (!nmspc::MatrixFactoryIn2D::if_generated_model_transformation_matrix)
	{
		nmspc::MatrixFactoryIn2D::refreshModelTransformationMatrix();
		for (std::int64_t i = 2; i <= 4; i++)
		{
			if (nmspc::MatrixFactoryIn2D::matrixes[i] != nullptr)
			{
				(*nmspc::MatrixFactoryIn2D::matrixes[1]) *= (*nmspc::MatrixFactoryIn2D::matrixes[i]);
			}
		}
		nmspc::MatrixFactoryIn2D::if_generated_model_transformation_matrix = true;
	}
	return nmspc::MatrixFactoryIn2D::matrixes[1];
}

const nmspc::Matrix3X3D* nmspc::MatrixFactoryIn2D::generateViewTransformationMatrix(const double& camera_x, const double& camera_y)
{
	std::lock_guard<std::mutex> lock(nmspc::MatrixFactoryIn2D::matrixes_mtx);
	if (nmspc::MatrixFactoryIn2D::matrixes[5] == nullptr)
	{
		nmspc::MatrixFactoryIn2D::matrixes[5] = nmspc::Matrix3X3D::generateIdentityMatrixPtr();
	}
	(*nmspc::MatrixFactoryIn2D::matrixes[5])[2][0] = -camera_x;
	(*nmspc::MatrixFactoryIn2D::matrixes[5])[2][1] = -camera_y;
	nmspc::MatrixFactoryIn2D::if_generated_final_matrix = false;
	return nmspc::MatrixFactoryIn2D::matrixes[5];
}

const nmspc::Matrix3X3D* nmspc::MatrixFactoryIn2D::generateProjectionTransformationMatrix(const double& left, const double& right, const double& bottom, const double& top)
{
	std::lock_guard<std::mutex> lock(nmspc::MatrixFactoryIn2D::matrixes_mtx);
	if (nmspc::MatrixFactoryIn2D::matrixes[6] == nullptr)
	{
		nmspc::MatrixFactoryIn2D::matrixes[6] = nmspc::Matrix3X3D::generateIdentityMatrixPtr();
	}
	(*nmspc::MatrixFactoryIn2D::matrixes[6])[0][0] = 2.0l / (right - left);
	(*nmspc::MatrixFactoryIn2D::matrixes[6])[1][1] = 2.0l / (top - bottom);
	(*nmspc::MatrixFactoryIn2D::matrixes[6])[2][0] = -((right + left) / (right - left));
	(*nmspc::MatrixFactoryIn2D::matrixes[6])[2][1] = -((top + bottom) / (top - bottom));
	nmspc::MatrixFactoryIn2D::if_generated_final_matrix = false;
	return nmspc::MatrixFactoryIn2D::matrixes[6];
}

const nmspc::Matrix3X3D* nmspc::MatrixFactoryIn2D::generateViewportTransformationMatrix(const double& width, const double& height)
{
	std::lock_guard<std::mutex> lock(nmspc::MatrixFactoryIn2D::matrixes_mtx);
	if (nmspc::MatrixFactoryIn2D::matrixes[7] == nullptr)
	{
		nmspc::MatrixFactoryIn2D::matrixes[7] = nmspc::Matrix3X3D::generateIdentityMatrixPtr();
	}
	(*nmspc::MatrixFactoryIn2D::matrixes[7])[0][0] = width / 2;
	(*nmspc::MatrixFactoryIn2D::matrixes[7])[1][1] = height / 2;
	(*nmspc::MatrixFactoryIn2D::matrixes[7])[2][0] = width / 2;
	(*nmspc::MatrixFactoryIn2D::matrixes[7])[2][1] = height / 2;
	nmspc::MatrixFactoryIn2D::if_generated_final_matrix = false;
	return nmspc::MatrixFactoryIn2D::matrixes[7];
}

const nmspc::Matrix3X3D* nmspc::MatrixFactoryIn2D::generateFinalMatrix()
{
	std::lock_guard<std::mutex> lock(nmspc::MatrixFactoryIn2D::matrixes_mtx);
	if (!nmspc::MatrixFactoryIn2D::if_generated_final_matrix)
	{
		nmspc::MatrixFactoryIn2D::refreshFinalMatrix();
		if (!nmspc::MatrixFactoryIn2D::if_generated_model_transformation_matrix)
		{
			nmspc::MatrixFactoryIn2D::refreshModelTransformationMatrix();
			for (std::int64_t i = 2; i <= 4; i++)
			{
				if (nmspc::MatrixFactoryIn2D::matrixes[i] != nullptr)
				{
					(*nmspc::MatrixFactoryIn2D::matrixes[1]) *= (*nmspc::MatrixFactoryIn2D::matrixes[i]);
				}
			}
			nmspc::MatrixFactoryIn2D::if_generated_model_transformation_matrix = true;

		}
		(*nmspc::MatrixFactoryIn2D::matrixes[0]) *= (*nmspc::MatrixFactoryIn2D::matrixes[1]);
		for (std::int64_t i = 5; i <= 7; i++)
		{
			if (nmspc::MatrixFactoryIn2D::matrixes[i] != nullptr)
			{
				(*nmspc::MatrixFactoryIn2D::matrixes[0]) *= (*nmspc::MatrixFactoryIn2D::matrixes[i]);
			}
		}
		nmspc::MatrixFactoryIn2D::if_generated_final_matrix = true;
	}
	return nmspc::MatrixFactoryIn2D::matrixes[0];
}

void nmspc::MatrixFactoryIn2D::refreshFunctionMatrixes()
{
	std::lock_guard<std::mutex> lock(nmspc::MatrixFactoryIn2D::matrixes_mtx);
	for (std::int64_t i = 2; i <= 7; i++)
	{
		if (nmspc::MatrixFactoryIn2D::matrixes[i] == nullptr)
		{
			nmspc::MatrixFactoryIn2D::matrixes[i] = nmspc::Matrix3X3D::generateIdentityMatrixPtr();
		}
		else
		{
			nmspc::MatrixFactoryIn2D::matrixes[i]->unitization();
		}
	}
	nmspc::MatrixFactoryIn2D::if_generated_final_matrix = false;
	nmspc::MatrixFactoryIn2D::if_generated_model_transformation_matrix = false;
}

void nmspc::MatrixFactoryIn2D::refreshMatrixAt(const std::int64_t& index)
{
	std::lock_guard<std::mutex> lock(nmspc::MatrixFactoryIn2D::matrixes_mtx);
	if (index < 0 || index >= 8) return;
	if (nmspc::MatrixFactoryIn2D::matrixes[index] == nullptr)
	{
		nmspc::MatrixFactoryIn2D::matrixes[index] = nmspc::Matrix3X3D::generateIdentityMatrixPtr();
	}
	else
	{
		nmspc::MatrixFactoryIn2D::matrixes[index]->unitization();
	}
	nmspc::MatrixFactoryIn2D::if_generated_final_matrix = false;
	if (index >= 1 && index <= 4)
	{
		nmspc::MatrixFactoryIn2D::if_generated_model_transformation_matrix = false;
	}
}

void nmspc::MatrixFactoryIn2D::refreshAll()
{
	std::lock_guard<std::mutex> lock(nmspc::MatrixFactoryIn2D::matrixes_mtx);
	for (std::int64_t i = 0; i <= 7; i++)
	{
		if (nmspc::MatrixFactoryIn2D::matrixes[i] == nullptr)
		{
			nmspc::MatrixFactoryIn2D::matrixes[i] = nmspc::Matrix3X3D::generateIdentityMatrixPtr();
		}
		else
		{
			nmspc::MatrixFactoryIn2D::matrixes[i]->unitization();
		}
	}
	nmspc::MatrixFactoryIn2D::if_generated_final_matrix = false;
	nmspc::MatrixFactoryIn2D::if_generated_model_transformation_matrix = false;
}

void nmspc::MatrixFactoryIn2D::push()
{
	std::lock_guard<std::mutex> lock1(nmspc::MatrixFactoryIn2D::matrixes_mtx);
	bool if_could_push = false;
	for (nmspc::Matrix3X3D*& matrix : nmspc::MatrixFactoryIn2D::matrixes)
	{
		if (matrix != nullptr)
		{
			if_could_push = true;
			break;
		}
	}
	if (if_could_push)
	{
		std::lock_guard<std::mutex> lock2(nmspc::MatrixFactoryIn2D::used_matrixes_mtx);
		for (std::int64_t i = 0; i <= 7; i++)
		{
			nmspc::MatrixFactoryIn2D::used_matrixes[i].push(nmspc::MatrixFactoryIn2D::matrixes[i]);
			nmspc::MatrixFactoryIn2D::matrixes[i] = nullptr;
		}
		nmspc::MatrixFactoryIn2D::used_if_generated_final_or_model_transformation_matrixes.push({ nmspc::MatrixFactoryIn2D::if_generated_final_matrix,nmspc::MatrixFactoryIn2D::if_generated_model_transformation_matrix });
		nmspc::MatrixFactoryIn2D::if_generated_final_matrix = false;
		nmspc::MatrixFactoryIn2D::if_generated_model_transformation_matrix = false;
	}
}

void nmspc::MatrixFactoryIn2D::pop()
{
	std::lock_guard<std::mutex> lock1(nmspc::MatrixFactoryIn2D::matrixes_mtx);
	for (nmspc::Matrix3X3D*& matrix : nmspc::MatrixFactoryIn2D::matrixes)
	{
		if (matrix != nullptr)
		{
			delete matrix;
		}
		matrix = nullptr;
	}
	nmspc::MatrixFactoryIn2D::if_generated_final_matrix = false;
	nmspc::MatrixFactoryIn2D::if_generated_model_transformation_matrix = false;
	std::lock_guard<std::mutex> lock2(nmspc::MatrixFactoryIn2D::used_matrixes_mtx);
	if (nmspc::MatrixFactoryIn2D::used_if_generated_final_or_model_transformation_matrixes.empty()) return;
	for (std::int64_t i = 0; i <= 7; i++)
	{
		nmspc::MatrixFactoryIn2D::matrixes[i] = nmspc::MatrixFactoryIn2D::used_matrixes[i].top();
		nmspc::MatrixFactoryIn2D::used_matrixes[i].pop();
	}
	nmspc::MatrixFactoryIn2D::if_generated_final_matrix = nmspc::MatrixFactoryIn2D::used_if_generated_final_or_model_transformation_matrixes.top().first;
	nmspc::MatrixFactoryIn2D::if_generated_model_transformation_matrix = nmspc::MatrixFactoryIn2D::used_if_generated_final_or_model_transformation_matrixes.top().second;
	nmspc::MatrixFactoryIn2D::used_if_generated_final_or_model_transformation_matrixes.pop();
}

void nmspc::MatrixFactoryIn2D::destory()
{
	std::lock_guard<std::mutex> lock1(nmspc::MatrixFactoryIn2D::matrixes_mtx);
	for (nmspc::Matrix3X3D*& cur_matrix : nmspc::MatrixFactoryIn2D::matrixes)
	{
		if (cur_matrix != nullptr)
		{
			delete cur_matrix;
		}
		cur_matrix = nullptr;
	}
	std::lock_guard<std::mutex> lock2(nmspc::MatrixFactoryIn2D::used_matrixes_mtx);
	for (std::stack<nmspc::Matrix3X3D*>& cur_matriexes : nmspc::MatrixFactoryIn2D::used_matrixes)
	{
		while (!cur_matriexes.empty())
		{
			delete cur_matriexes.top();
			cur_matriexes.pop();
		}
	}
	while (!nmspc::MatrixFactoryIn2D::used_if_generated_final_or_model_transformation_matrixes.empty())
	{
		nmspc::MatrixFactoryIn2D::used_if_generated_final_or_model_transformation_matrixes.pop();
	}
}

const nmspc::Matrix3X3D* nmspc::MatrixFactoryIn2D::getScaleMatrix()
{
	std::lock_guard<std::mutex> lock(nmspc::MatrixFactoryIn2D::matrixes_mtx);
	if (nmspc::MatrixFactoryIn2D::matrixes[2] == nullptr)
	{
		nmspc::MatrixFactoryIn2D::matrixes[2] = nmspc::Matrix3X3D::generateIdentityMatrixPtr();
	}
	return nmspc::MatrixFactoryIn2D::matrixes[2];
}

const nmspc::Matrix3X3D* nmspc::MatrixFactoryIn2D::getRotateMatrix()
{
	std::lock_guard<std::mutex> lock(nmspc::MatrixFactoryIn2D::matrixes_mtx);
	if (nmspc::MatrixFactoryIn2D::matrixes[3] == nullptr)
	{
		nmspc::MatrixFactoryIn2D::matrixes[3] = nmspc::Matrix3X3D::generateIdentityMatrixPtr();
	}
	return nmspc::MatrixFactoryIn2D::matrixes[3];
}

const nmspc::Matrix3X3D* nmspc::MatrixFactoryIn2D::getTranslateMatrix()
{
	std::lock_guard<std::mutex> lock(nmspc::MatrixFactoryIn2D::matrixes_mtx);
	if (nmspc::MatrixFactoryIn2D::matrixes[4] == nullptr)
	{
		nmspc::MatrixFactoryIn2D::matrixes[4] = nmspc::Matrix3X3D::generateIdentityMatrixPtr();
	}
	return nmspc::MatrixFactoryIn2D::matrixes[4];
}

const nmspc::Matrix3X3D* nmspc::MatrixFactoryIn2D::getModelTransformationMatrix()
{
	return nmspc::MatrixFactoryIn2D::generateModelTransformationMatrix();
}

const nmspc::Matrix3X3D* nmspc::MatrixFactoryIn2D::getViewTransformationMatrix()
{
	std::lock_guard<std::mutex> lock(nmspc::MatrixFactoryIn2D::matrixes_mtx);
	if (nmspc::MatrixFactoryIn2D::matrixes[5] == nullptr)
	{
		nmspc::MatrixFactoryIn2D::matrixes[5] = nmspc::Matrix3X3D::generateIdentityMatrixPtr();
	}
	return nmspc::MatrixFactoryIn2D::matrixes[5];
}

const nmspc::Matrix3X3D* nmspc::MatrixFactoryIn2D::getProjectionTransformationMatrix()
{
	std::lock_guard<std::mutex> lock(nmspc::MatrixFactoryIn2D::matrixes_mtx);
	if (nmspc::MatrixFactoryIn2D::matrixes[6] == nullptr)
	{
		nmspc::MatrixFactoryIn2D::matrixes[6] = nmspc::Matrix3X3D::generateIdentityMatrixPtr();
	}
	return nmspc::MatrixFactoryIn2D::matrixes[6];
}

const nmspc::Matrix3X3D* nmspc::MatrixFactoryIn2D::getViewportTransformationMatrix()
{
	std::lock_guard<std::mutex> lock(nmspc::MatrixFactoryIn2D::matrixes_mtx);
	if (nmspc::MatrixFactoryIn2D::matrixes[7] == nullptr)
	{
		nmspc::MatrixFactoryIn2D::matrixes[7] = nmspc::Matrix3X3D::generateIdentityMatrixPtr();
	}
	return nmspc::MatrixFactoryIn2D::matrixes[7];
}

const nmspc::Matrix3X3D* nmspc::MatrixFactoryIn2D::getFinalMatrix()
{
	return nmspc::MatrixFactoryIn2D::generateFinalMatrix();
}
